/*-
 * ProjectJpaRepository.java
 *
 * Date: 2016年4月29日
 * Time: 下午3:50:44
 *
 * 版权所有©2012-2013 rengh
 */

package com.lmx.persistence.service;

import io.katharsis.queryParams.QueryParams;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.lmx.common.constants.CommonConstants;
import com.lmx.common.context.ActionContextHolder;
import com.lmx.common.util.CommonUtil;
import com.lmx.repoDomain.tmodel.Customer;
import com.lmx.repoDomain.tmodel.Dicttype;
import com.lmx.repoDomain.tmodel.Privilege;
import com.lmx.repoDomain.tmodel.Role;
import com.lmx.repoDomain.tmodel.StaffCustomer;
import com.lmx.repoDomain.tmodel.Tenant;
import com.lmx.repoDomain.tmodel.UserPrivate;
//import com.lmx.repoDomain.model.*;
import com.lmx.repoDomain.tmodel.UserSession;//huibati
import com.lmx.repoDomain.tmodel.business.Organization;
import com.lmx.repoDomain.tmodel.business.User;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.jpa.impl.JPAQuery;

/**
 * #{description}
 *
 * @author Administrator
 * @version 1.00
 */
@Service
@Scope("prototype")
public class UserSessionService<T> {
	private Log logger = LogFactory.getLog(this.getClass());

	@PersistenceContext
	private EntityManager em;

	@Autowired
	protected GenericService dslJpaService;

	@Autowired
	protected UserService userService;

	@Autowired
	protected RoleService roleService;

	@Autowired
	protected CommonService commonService;

	@Autowired
	private WeiXinService weixinService;

	/**
	 * 用户登录
	 *
	 * @param requestParams
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Iterable<UserSession> login(final QueryParams requestParams) {
		final PathBuilder<?> builder = new PathBuilder<UserPrivate>(UserPrivate.class, "user");
		Map<String, String> keyMap = CommonUtil.getKeyMapByFilter(requestParams);
		PathBuilder<Role> rolePath = new PathBuilder<Role>(Role.class, "user.role");// user对应角色
		PathBuilder<Privilege> privilegePath = new PathBuilder<Privilege>(Privilege.class,
				"role.privileges");// role权限
		PathBuilder<Dicttype> userStatusPath = new PathBuilder<Dicttype>(Dicttype.class,
				"user.staffStatus");// user状态
		PathBuilder<Tenant> tenantPath = new PathBuilder<Tenant>(Tenant.class, "user.tenant");
		BooleanExpression predicate = buildPredicateForLogin(builder, requestParams);
		BooleanExpression predicateOr = predicate;
		final JPAQuery query = new JPAQuery(em);
		// 关联查出角色和权限数据
		Path<Role> roleAlias = new PathBuilder<Role>(Role.class, "role");
		Path<Privilege> privilegeAlias = new PathBuilder<Privilege>(Privilege.class, "privileges");
		Path<Tenant> tenantAlias = new PathBuilder<Tenant>(Tenant.class, "tenant");
		BooleanExpression texpUser = builder.getNumber("delStatus", Long.class).eq((long) 0);
		BooleanExpression texpUserStatus = userStatusPath.getString("typecode").notLike(
				CommonConstants.DICTTYPE.EMPLOYEE_STATUS_2.label());// userstatus可用
		BooleanExpression texpRole = rolePath.getNumber("delStatus", Long.class).eq((long) 0);
		BooleanExpression texpTenantStatus = tenantPath.getString("status.typecode").eq(
				CommonConstants.DICTTYPE.TENANT_STATUS_1.label());// tenantstatus已发布
		BooleanExpression texpTenantUser = tenantPath.getNumber("id", Long.class).gt((long) 999);// tenantid>999
		BooleanExpression texpTenantAdmin = tenantPath.getNumber("id", Long.class).lt((long) 1000);// tenantid<1000
		// tenant id<1000
		predicate = predicate.and(texpUser);
		predicate = predicate.and(texpUserStatus);
		predicate = predicate.and(texpRole);
		// predicate = predicate.and(texpTenantStatus);
		predicate = predicate.and(texpTenantAdmin);
		// tenant id>999
		predicateOr = predicateOr.and(texpUser);
		predicateOr = predicateOr.and(texpUserStatus);
		predicateOr = predicateOr.and(texpRole);
		predicateOr = predicateOr.and(texpTenantUser);
		predicateOr = predicateOr.and(texpTenantStatus);

		// predicate = predicate.or(predicateOr);
		ArrayList<UserSession> userSessionList = new ArrayList<UserSession>();
		try {
			query.from(builder).leftJoin(rolePath, roleAlias).fetchJoin()
					.leftJoin(privilegePath, privilegeAlias).fetchJoin()
					.leftJoin(tenantPath, tenantAlias).fetchJoin()
					.where(predicate.or((predicateOr)));
			Iterator<UserPrivate> iterator = query.fetch().iterator();
			if (iterator.hasNext()) {
				UserPrivate userPrivate = iterator.next();
				// 设置返回登录信息
				UserSession userSession = new UserSession();
				BeanUtils.copyProperties(userPrivate, userSession);
				UUID uuid = UUID.randomUUID();
				String token = uuid.toString();

				// 康颐用户登录后设置customerId
				User user = userService.getUserById(userPrivate.getId());
				if (user.getCustomers() != null && user.getCustomers().size() > 0) {
					userSession.setCustomerId(user.getCustomers().get(0).getId());
				}
				userSession.setToken(token);
				// 网站初始化网络请求优化 17/7/17 ytche
				Organization org = userSession.getOrg();
				if (org != null) {
					org.setAdmin(null);
				}
				// 重新登录时删除失效session
				if (keyMap.containsKey("oldToken")) {
					String oldToken = keyMap.get("oldToken");
					if (StringUtils.isNotBlank(oldToken)
							&& ActionContextHolder.getEvaHolder().containsKey(oldToken)) {
						ActionContextHolder.getEvaHolder().remove(oldToken);
					}
					// 清空websocketsession
					// ActionContextHolder.getUidSocketSessionHolder().remove(userPrivate.getId());
				}
				userSessionList.add(userSession);
				// 保存登录信息
				// User user = new User();
				// BeanUtils.copyProperties(userPrivate,user);
				// ActionContextHolder.getContext().setUser(user);
				// ActionContextHolder.getEvaHolder().put(token, user);
				ActionContextHolder.getEvaHolder().put(token, userSession);
				ActionContextHolder.getUidTokenHolder().put(userPrivate.getId().toString(), token);
				logger.debug("socket:login_userId:" + userPrivate.getId());
			}

		} catch (Exception e) {
			logger.error("登录出错：", e);
		}

		return userSessionList;
	}

	/*
	 * 查询参数转换(登录) huibati
	 */
	public BooleanExpression buildPredicateForLogin(PathBuilder<?> pathBuilder,
			QueryParams requestParams) {
		BooleanExpression result = null;
		Iterator<String> it = requestParams.getFilters().getParams().keySet().iterator();
		Map<String, BooleanExpression> beMap = new HashMap<String, BooleanExpression>();
		/*
		 * while(it.hasNext()){ String key = it.next();
		 * TypedParams<FilterParams> filters = requestParams.getFilters();
		 * Map<String, FilterParams> params = filters.getParams();
		 * Iterator<String> paramsIt = params.keySet().iterator();
		 * while(paramsIt.hasNext()){ String pkey = paramsIt.next();
		 * FilterParams fp = params.get(pkey); Map<String, Set<String>> map =
		 * fp.getParams(); Iterator<String> fpIt = map.keySet().iterator();
		 * 
		 * //条件初始化 String fpkey = null; String value = null; //兼容
		 * filter[0][field] filter[field] if(!"0".equals(pkey)) { fpkey = pkey;
		 * value = map.get("").iterator().next(); beMap =
		 * condition(beMap,pathBuilder,fpkey,value); }else{ while
		 * (fpIt.hasNext()){ fpkey = fpIt.next(); Set<String> keyValue =
		 * map.get(fpkey); Iterator<String> vit = keyValue.iterator();
		 * while(vit.hasNext()){ value = vit.next(); beMap =
		 * condition(beMap,pathBuilder,fpkey,value); } } } } }
		 */

		// 获取参数map
		Map<String, String> keyMap = CommonUtil.getKeyMapByFilter(requestParams);
		Set<String> keySet = keyMap.keySet();
		for (String key : keySet) {
			beMap = condition(beMap, pathBuilder, key, keyMap.get(key));
		}
		if (beMap.get("loginName") != null && beMap.get("password") != null) {
			result = beMap.get("loginName");
			result = result.and(beMap.get("password"));
		} else {
			result = pathBuilder.getNumber("id", BigDecimal.class).lt(new BigDecimal(0));
		}
		if (beMap.get("tenant.id") != null) {
			result = result.and(beMap.get("tenant.id"));
		}
		return result;
	}

	/**
	 * 获取条件
	 *
	 * @param beMap
	 * @param pathBuilder
	 * @param fpkey
	 * @param value
	 * @return map key：or/and value:be
	 */
	public Map<String, BooleanExpression> condition(Map<String, BooleanExpression> beMap,
			PathBuilder<?> pathBuilder, String fpkey, String value) {
		BooleanExpression be = null;

		logger.debug(fpkey + ":" + value);
		if (!"tenant.id".equals(fpkey)) {
			if (value == null || value.length() == 0) {
				return null;
			}
		}

		// 获取be（单个条件）
		if ("loginName".equals(fpkey)) {
			be = pathBuilder.getString("loginName").eq(new String(value));
			beMap.put("loginName", be);
		}
		if ("password".equals(fpkey)) {
			be = pathBuilder.getString("password").eq(new String(value));
			beMap.put("password", be);
		}
		if ("tenant.id".equals(fpkey) && value != null && !"".equals(value)
				&& value.matches("\\d+")) {
			be = pathBuilder.get("tenant.id").eq(Long.parseLong(value));
			beMap.put("tenant.id", be);
		}
		return beMap;
	}

	/**
	 * 绑定老人
	 *
	 * @param requestParams
	 * @return
	 */
	@Transactional
	public Iterable<UserSession> bindCustomer(String name, String birthday, String code) {
		logger.debug("weixin code:" + code);
		String openId = "";
		if (code != null && !"".equals(code)) {
			openId = weixinService.getOpenIDByCode(code);
		}
		List<UserSession> userSessionList = new ArrayList<>();
		UserSession userSession = new UserSession();
		// birthday 转化为 时间戳
		// if (name == null || birthday == null || openId==null ||
		// "".equals(name) || "".equals(birthday) || "".equals(openId) ) {
		if (name == null || birthday == null || "".equals(name) || "".equals(birthday)) {

		} else {
			Integer birth = Integer.parseInt(birthday);
			Customer ct = null;
			StringBuilder query = new StringBuilder(
					"select c from Customer c where c.name = ?1 and c.birthday = ?2 and c.delStatus != 1");
			List dataList = this.em.createQuery(query.toString()).setParameter(1, name)
					.setParameter(2, birth).getResultList();
			if (dataList.size() > 0) {
				ct = (Customer) dataList.get(0);
			}
			if (ct == null) {

			} else {
				// 产生新的user
				User user = new User();
				int loginNameFlag = 0;
				String loginName = CommonUtil.getStringRandom(8);
				while (loginNameFlag == 0) {
					User temp = userService.getUserByLoginName(loginName);
					if (temp == null) {
						loginNameFlag = 1;
						break;
					}
					loginName = CommonUtil.getStringRandom(8);
				}
				Role role = roleService.getRoleByTenantAndCode(ct.getTenant().getId(), "wechat");
				Tenant tenant = new Tenant();
				tenant.setId(ct.getTenant().getId());
				user.setRole(role);
				user.setLoginName(loginName);// 如何 产生登录名
				user.setDelStatus((short) 0);
				user.setPasscode(CommonUtil.stringMD5("111111"));// 设置密码 登录名
				user.setPassword(CommonUtil.stringMD5("111111"));// 设置密码 登录名
				user.setTenant(tenant);
				user.setStaffStatus(commonService
						.getDicttype(CommonConstants.DICTTYPE.EMPLOYEE_STATUS_1.label()));
				user.setOpenId(openId);
				dslJpaService.setEntityClass(User.class);
				dslJpaService.create(user);
				// user 关注此老人
				StaffCustomer sc = new StaffCustomer();
				sc.setCustomer(ct);
				sc.setStaff(user);
				sc.setTenant(tenant);
				sc.setDelStatus((short) 0);
				dslJpaService.setEntityClass(StaffCustomer.class);
				dslJpaService.create(sc);
				// 建立新的 UserSession UserPrivate
				UserPrivate userPrivate = new UserPrivate();
				BeanUtils.copyProperties(user, userPrivate);

				BeanUtils.copyProperties(user, userSession);
				userSession.setPassword(user.getPasscode());
				UUID uuid = UUID.randomUUID();
				String token = uuid.toString();
				userSession.setToken(token);
				userSession.setTenant(tenant);
				ActionContextHolder.getEvaHolder().put(token, userSession);
				ActionContextHolder.getUidTokenHolder().put(userPrivate.getId().toString(), token);
			}

		}
		userSessionList.add(userSession);
		return userSessionList;
	}

}
